package kayao.client.scene.objects;

import javax.microedition.khronos.opengles.GL10;

import kayao.client.data.SharedMemory;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.opengl.GLUtils;
import android.opengl.Matrix;

import com.chopsticks3d.scene.Material;
import com.chopsticks3d.scene.MeshNode;
import com.chopsticks3d.scene.shape.Plane;

/**
 * A node above a car to show the name of the client controlling it
 */
public class CarNameNode extends MeshNode {
	public static final int TEXT_COLOR_TEAMMATE = 0xFF11FF11;
	public static final int TEXT_COLOR_ENEMY = 0xFFFF1111;
	public static final int TEXT_SIZE = 30;
	public static final String TEXT_FONT = "fonts/SHOWG.TTF";
	public static final int TEXTURE_WIDTH = 256;
	public static final int TEXTURE_HEIGHT = 64;
	
	private static final Plane mPlaneMesh = new Plane();
	private static Paint sPaint = null;
	private static int sTextPositionY;
	
	private int[] mTextureNameWorkspace = new int[1];
	private int mTextureId = -1;
	private String mName;

	// Used for calculations
	private float[] x  = new float[3];
	private float[] y  = new float[3];
	private float[] z  = new float[3];
	private float mag;

	public CarNameNode(String name, boolean teammate) {
		super(mPlaneMesh);
		mName = name;
		
		if (sPaint == null) {
			createPaint(teammate);
		}
	}

	@Override
	public void onDraw(GL10 gl) {
		gl.glPushMatrix();

		gl.glEnable(GL10.GL_ALPHA_TEST);
		gl.glAlphaFunc(GL10.GL_GEQUAL, 0.9f);
		gl.glDisable(GL10.GL_LIGHTING);

		if (mParent != null) {
			System.arraycopy(mParent.getTransformation(), 0, mModelView, 0, 16);
		} else {
			Matrix.setIdentityM(mModelView, 0);
		}

		Matrix.translateM(mModelView, 0, mX, mY, mZ);
		faceDisplay();
		Matrix.scaleM(mModelView, 0, mScaleX, mScaleY, mScaleZ);

		gl.glMultMatrixf(mModelView, 0);

		if (mTextureId == -1) {
			createTexture(gl);
		}
		gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
		
		Material.remove(gl);

		mMesh.onDraw(gl);

		gl.glDisable(GL10.GL_ALPHA_TEST);
		gl.glEnable(GL10.GL_LIGHTING);

		gl.glPopMatrix();

		if (mChild != null)
			mChild.onDraw(gl);

		if (mSibling != null)
			mSibling.onDraw(gl);
	}
	
	private void createPaint(boolean teammate) {
		// Create paint with the text properties
        sPaint = new Paint();
        if (teammate) {
        	sPaint.setColor(TEXT_COLOR_TEAMMATE);
        } else {
        	sPaint.setColor(TEXT_COLOR_ENEMY);
        }
        
        sPaint.setTextSize(TEXT_SIZE);
        sPaint.setTextAlign(Paint.Align.CENTER);
//        sPaint.setTypeface(Typeface.createFromAsset(SharedMemory.getInstance().getContext().getAssets(), TEXT_FONT));
        sTextPositionY = (int)Math.ceil(sPaint.getTextSize() - sPaint.getTextSize() * 0.2f);
	}
	
	private void createTexture(GL10 gl) {
		this.setScaleX(4);
		Bitmap bitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(bitmap);
		
		gl.glGenTextures(1, mTextureNameWorkspace, 0);
		mTextureId = mTextureNameWorkspace[0];
		
		gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
		
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
        
        bitmap.eraseColor(Color.TRANSPARENT);
		canvas.drawText(mName, TEXTURE_WIDTH/2, sTextPositionY, sPaint);
        
		//Some textures transformations to display it correctly
		android.graphics.Matrix matrix = new android.graphics.Matrix();
		matrix.postRotate(180);
		matrix.postScale(-1, 1);
		Bitmap bitmap2 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
		
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap2, 0);
	}

	/**
	 * Make the node face the display by using the camera view vector
	 * of the camera in the shared memory.
	 */
	private void faceDisplay() {
		z = SharedMemory.getInstance().getCamera().getLookVector();

		// Y vector
		y[0] = 0;
		y[1] = 1;
		y[2] = 0;

		// X vector = Y cross Z    	
		x[0] = y[1] * z[2] - y[2] * z[1];
		x[1] = -y[0] * z[2] + y[2] * z[0];
		x[2] = y[0] * z[1] - y[1] * z[0];

		mag = Matrix.length(x[0], x[1], x[2]);
		if (mag > 0) {
			mag = 1/mag;
			x[0] *= mag;
			x[1] *= mag;
			x[2] *= mag;
		}

		// Recompute Y = Z cross X    	
		y[0] = z[1] * x[2] - z[2] * x[1];
		y[1] = -z[0] * x[2] + z[2] * x[0];
		y[2] = z[0] * x[1] - z[1] * x[0];

		// cross product gives area of parallelogram, which is < 1.0 for
		// non-perpendicular unit-length vectors; so normalize y here
		mag = Matrix.length(y[0], y[1], y[2]);
		if (mag > 0) {
			mag = 1/mag;
			y[0] *= mag;
			y[1] *= mag;
			y[2] *= mag;
		}

		synchronized(mModelView) {
			mModelView[0] = x[0];
			mModelView[1] = x[1];
			mModelView[2] = x[2];
			mModelView[3] = 0.0f;
			mModelView[4] = y[0];
			mModelView[5] = y[1];
			mModelView[6] = y[2];
			mModelView[7] = 0.0f;
			mModelView[8] = z[0];
			mModelView[9] = z[1];
			mModelView[10] = z[2];
			mModelView[11] = 0.0f;
		}
	}
}
